#include <lwip/netif.h>
#include <lwip/ip.h>
#include <lwip/tcp.h>
#include <lwip/init.h>
#include <netif/etharp.h>
#include <lwip/udp.h>
#include <lwip/tcpip.h>
#include <lwip/dhcp.h>
#include <lwip/sockets.h>
#include <lwip/ip_addr.h>
#include <stdio.h>
#include <stdlib.h>
#include <nxos.h>

/* lwip interface */
extern err_t ethernetif_init(struct netif *netif);
extern void ethernetif_input(struct netif *netif);
extern void httpserver_init();

struct netif lwip_netif;

void lwip_init_task(void)
{
    ip_addr_t ipaddr, netmask, gateway;
    printf("[Net] net server init with lwip core\n");
#if NO_SYS == 1
    lwip_init();
#else
    tcpip_init(NULL, NULL);
#endif
    IP4_ADDR(&ipaddr, 192,168,0,200);
    IP4_ADDR(&gateway, 192,168,0,1);
    IP4_ADDR(&netmask, 255,255,0, 0);
    printf("  addr : %d.%.d.%d.%d\n", 
        ((unsigned char *)&ipaddr.addr)[0],
        ((unsigned char *)&ipaddr.addr)[1],
        ((unsigned char *)&ipaddr.addr)[2],
        ((unsigned char *)&ipaddr.addr)[3]);
    printf("  netmask : %d.%.d.%d.%d\n", 
        ((unsigned char *)&netmask.addr)[0],
        ((unsigned char *)&netmask.addr)[1],
        ((unsigned char *)&netmask.addr)[2],
        ((unsigned char *)&netmask.addr)[3]);
    printf("  gw : %d.%.d.%d.%d\n",
        ((unsigned char *)&gateway.addr)[0],
        ((unsigned char *)&gateway.addr)[1],
        ((unsigned char *)&gateway.addr)[2],
        ((unsigned char *)&gateway.addr)[3]);
#if NO_SYS == 1
    netif_add(&lwip_netif, &ipaddr, &netmask, &gateway, NULL, ethernetif_init, ethernet_input);
#else    
    netif_add(&lwip_netif, &ipaddr, &netmask, &gateway, NULL, ethernetif_init, tcpip_input);
#endif    
    netif_set_default(&lwip_netif);
    netif_set_up(&lwip_netif);
}

NX_IMPORT NX_Size NET_Dispatch(NX_IpcMsg *ipcMsg);

NX_PRIVATE void NET_IpcHandler(NX_IpcMsg *ipc_msg)
{
    NX_Size ret = NET_Dispatch(ipc_msg);
	// NX_Printf("net: ret:%d\n", ret);
    NX_IpcReturn(ret);
}

NX_IMPORT void SockCloseSignalHandler(NX_SignalInfo * info);

int main(int argc, char *argv[])
{
    if (NX_IpcBind("net", NET_IpcHandler, 32) < 0)
    {
        NX_Printf("NET bind error!\n");
        return -1;
    }

    lwip_init_task();

    NX_SignalAttr attr;
    NX_SignalInitAttr(&attr, SockCloseSignalHandler, 0);
    NX_SignalSetAttr(NX_SIGNAL_UOBJECT, &attr);

    while(1) {
        ethernetif_input(&lwip_netif);
        //todo: add your own user code here
        NX_ThreadSleep(5);
    }

    return 0;
}
